package com.woniuxy.aspectj.anno;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Aspect//aop要使用的 表示这个类是个切面
@Component//这个是spring需要的，表示这个类是个组件，可以自动帮我注册到IOC容器中成为bean 类似<bean id="myAspectJ" class="">
//AspectJ的基于注解的AOP实现！
public class MyAnnoAspectJ {
    @Pointcut("execution(* com.woniuxy.service..*.*(..))")
    //前置通知
    @Before("myPointCut()")
    public void myBefore(JoinPoint joinPoint) {
        System.out.println("前置通知：模拟判断是否有@Transcational注解");
        System.out.println("目标类：" + joinPoint.getTarget().getClass().getName());
        System.out.println(",被织入的增强目标的方法是：" + joinPoint.getSignature().getName());
    }
    //后置通知
    @AfterReturning("myPointCut()")
    public void myAfterReturning(JoinPoint joinPoint) {
        System.out.println("后置通知：模拟事务的提交");
        System.out.println("目标类：" + joinPoint.getTarget().getClass().getName());
        System.out.println(",被织入的增强目标的方法是：" + joinPoint.getSignature().getName());
    }
    //环绕通知：不推荐使用，功能强大
    @Around("myPointCut()")
    public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕开始：执行目标方法之前……");
        Object []args = proceedingJoinPoint.getArgs();
        args[0]=0;
        args[1]=0;
        //proceed放行
        List proceed=(List)proceedingJoinPoint.proceed(args);
        proceed=new ArrayList<>();
        Map<Object,Object> objectObjectMap=new HashMap<>();
        objectObjectMap.put("a","你中病毒了");
        objectObjectMap.put("b","请支付比特币0.09个");
        proceed.add(objectObjectMap);
        System.out.println("环绕结束：执行目标方法之后……");
        return proceed;
    }



    //异常通知
    @AfterThrowing(value="myPointCut()",throwing = "e")
    public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
        System.out.println("异常通知");
        System.out.println("报错信息"+e.getMessage());
    }
    //最终通知
    @After("myPointCut()")
    public  void myAfter(){
        System.out.println("最终通知：模拟方法结束后释放资源，关闭SqlSession");
    }
}
